#include <stdio.h>
#include <stdlib.h>

#include <unistd.h>

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <string.h>

#include <wait.h>

#define MSGSZ     128


typedef struct msgbuf {
	long mtype;
	char mtext[MSGSZ];
} message_buf;

int main(void) {

    int pid_filho, pid_pai;
	int j, status;

    int msqid;
    int msgflg = IPC_CREAT | 0666;

    key_t key;
	message_buf sbuf, rbuf;
    size_t buf_length;

	pid_pai = getpid();
    printf("PID Processo corrente: %d\n", getpid());

    //criando novo processo
    pid_filho = fork();

    if (pid_filho != 0){
        //processo pai

        printf("[Pai] PID pai: %d, PID filho: %d\n", pid_pai, pid_filho);

		// Criando canal de comunicação
        key = 12345;
        if ((msqid = msgget(key, msgflg )) < 0) {
            perror("msgget");
            exit(1);
        }

		// Criando mensagem
		sbuf.mtype = 1;
        strcpy(sbuf.mtext, "Oi Filho");
        buf_length = strlen(sbuf.mtext) + 1;

		// Enviando mensagem
        if (msgsnd(msqid, &sbuf, buf_length, 0) < 0) {
           	printf ("[Pai] Erro ao enviar mensagem: %d, %s\n", msqid, sbuf.mtext);
            perror("msgsnd");
            exit(1);
		} else {
          	printf("[Pai] Mensagem enviada: \"%s\" \n", sbuf.mtext);
		}

		// Recebendo mensagem
        if (msgrcv(msqid, &rbuf, MSGSZ, 2, 0) < 0) {
            perror("msgrcv");
            exit(1);
        }
        printf("[Pai] Mensagem recebida: \"%s\"\n", rbuf.mtext);

		// Recebendo mensagem
        if (msgrcv(msqid, &rbuf, MSGSZ, 1, 0) < 0) {
            perror("msgrcv");
            exit(1);
        }
        printf("[Pai] Mensagem recebida: \"%s\"\n", rbuf.mtext);

		// Esperando filho terminar
		wait(&status);

		// Fechando canal de comunicação
		close(msqid);

		printf("[Pai] Acabei!\n");
        exit(0);
    } else {
        //processo filho

        printf("[Filho] PID pai: %d, PID filho: %d\n", pid_pai, getpid());

		// Criando canal de comunicação
        key = 12345;
        if ((msqid = msgget(key, 0666)) < 0) {
            perror("msgget");
            exit(1);
        }

		// Recebendo mensagem
        if (msgrcv(msqid, &rbuf, MSGSZ, 1, 0) < 0) {
            perror("msgrcv");
            exit(1);
        }
        printf("[Filho] Mensagem recebida: \"%s\"\n", rbuf.mtext);
		
		// Criando mensagem
		sbuf.mtype = 2;
        strcpy(sbuf.mtext, "Oi Pai");
        buf_length = strlen(sbuf.mtext) + 1;

		// Enviando mensagem
        if (msgsnd(msqid, &sbuf, buf_length, 0) < 0) {
           	printf ("[Filho] Erro ao enviar mensagem: %d, %s\n", msqid, sbuf.mtext);
            perror("msgsnd");
            exit(1);
		} else {
          	printf("[Filho] Mensagem enviada: \"%s\" \n", sbuf.mtext);
		}

		// Executando o for
		for(j=0; j<=10000; j++);

		// Criando mensagem
		sbuf.mtype = 1;
		sprintf(sbuf.mtext, "j = %d", j);
        buf_length = strlen(sbuf.mtext) + 1;

		// Enviando mensagem
        if (msgsnd(msqid, &sbuf, buf_length, 0) < 0) {
           	printf ("[Filho] Erro ao enviar mensagem: %d, %s\n", msqid, sbuf.mtext);
            perror("msgsnd");
            exit(1);
		} else {
          	printf("[Filho] Mensagem enviada: \"%s\" \n", sbuf.mtext);
		}

		// Executando comando
		printf("[Filho] Antes do ls\n");
		execl("/bin/ls", "/bin/ls", NULL);
		printf("[Filho] Depois do ls\n");

		// Fechando canal de comunicação
		close(msqid);

		printf("[Filho] Acabei!\n");
		exit(0);
    }
    exit(0);
}

